dojo.provide("miaigo.model.Move");

dojo.require("miaigo.model.BoardState");
dojo.require("miaigo.model.MoveValidator");

dojo.declare(
    "miaigo.model.Move",
    null,
    {
	// miaigo.model.Node
	srcNode: null,

	// Parent MoveTree
	_parent: null,

	// Array of MoveTree as move alternations
	_alterations: null,

	// board state after this move
	_boardState: null,

	// a PointSet to indicate the captured stones at this move
	_captured: null,


	_error: null,

	// createParam:
	// {
	//   srcNode: miaigo.model.Node
	//     - A node with type is "move", give the move's location, stone, etc.
	//   baseState: miaigo.model.BoardState
	//     - The board state before applying this move.
	// }
	constructor: function(createParam)
	{
	    if (createParam)
	    {
		this.srcNode = createParam.srcNode;
	    }

	    this._alterations = [];

	    //TODO: create srcNode if not given?

	    if (this.srcNode)
	    {
		this._buildFromNode(createParam.baseState);
	    }
	},

	getError: function()
	{
	    return this._error;
	},

	getPoint: function()
	{
	    var blackMove = this.srcNode.getAttribute("blackMove");
	    var whiteMove = this.srcNode.getAttribute("whiteMove");

	    if (blackMove)
	    {
		return blackMove;
	    }
	    else
	    {
		return whiteMove;
	    }
	},

	getStone: function()
	{
	    var blackMove = this.srcNode.getAttribute("blackMove");
	    var whiteMove = this.srcNode.getAttribute("whiteMove");

	    if (blackMove)
	    {
		return "black";
	    }
	    else if (whiteMove)
	    {
		return "white";
	    }

	    return null;
	},

	isBlack: function()
	{
	    return (this.getStone() == "black");
	},

	isWhite: function()
	{
	    return (this.getStone() == "white");
	},

	setParent: function(parentTree)
	{
	    this._parent = parentTree;
	},

	getParent: function()
	{
	    return this._parent;
	},

	addAlteration: function(/* MoveTree */alter)
	{
	    this._alterations.push(alter);
	},

	getAlternation: function(/* Number */index)
	{
	    return this._alternations[index];
	},

	getBoardState: function()
	{
	    return this._boardState;
	},

	getCaptured: function()
	{
	    if (this._captured)
	    {
		return this._captured.getAllPoints();
	    }
	    else
	    {
		return null;
	    }
	},

	_buildFromNode: function(/* miaigo.model.BoardState */baseState)
	{
	    if (baseState)
	    {
		var movePoint = this.getPoint();
		var moveParam =
		    {
			stone: this.getStone(),
			x: movePoint.x,
			y: movePoint.y
		    };

		if (miaigo.model.MoveValidator.testPlace(baseState, moveParam))
		{
		    // create a new state base on given state
		    this._boardState = baseState.clone();

		    // make move on new state
		    if (!this._boardState.makeMove(moveParam))
		    {
			this._error = "Cannot make move base on given state";
			return;
		    }

		    // test captured stones on new state
		    var captureResult = miaigo.model.MoveValidator.testCapture(this._boardState);

		    // if can capture, the move is valid
		    if (moveParam.stone == "black")
		    {
			if (captureResult.whiteBlocks && captureResult.whiteBlocks.length > 0)
			{
			    // remove blocks captured
			    this._captured = this._boardState.removeBlocks(captureResult.whiteBlocks);
			    // a valid move with white stones captured
			    return;
			}
		    }
		    else if (moveParam.stone == "white")
		    {
			if (captureResult.blackBlocks && captureResult.blackBlocks.length > 0)
			{
			    // remove blocks captured
			    this._captured = this._boardState.removeBlocks(captureResult.blackBlocks);
			    // a valid move with black stones captured
			    return;
			}
		    }

		    // if cannot capture, cannot suicide
		    if (moveParam.stone == "black" && captureResult.blackBlocks && captureResult.blackBlocks.length > 0)
		    {
			this._error = "Black suicide";
		    }

		    if (moveParam.stone == "white" && captureResult.whiteBlocks && captureResult.whiteBlocks.length > 0)
		    {
			this._error = "White suicide";
		    }

		    // a valid move, without capture
		}
		else
		{
		    this._error = "the given move point is not valid";
		}
	    }
	    else
	    {
		// no base state given
		this._error = "no base state";
	    }
	}
    });